<script setup>
import { computed, reactive, ref, watch } from "vue";
import noteServeRequest from "@/utils/request";
import { useUserStore } from "@/stores/userStore";
import { storeToRefs } from "pinia";
import VuePictureCropper, { cropper } from 'vue-picture-cropper'
import userApi from '@/utils/api/userApi'


// 共享库（用户信息）
const userStore = useUserStore();
// 用户信息（头像，昵称，等级，编号）
const { head_image, nick_name, level_info, email, time } = storeToRefs(userStore);
// 设置用户的基本信息
const { setUserBasicInfo } = userStore;

// 是否展开抽屉
const show = ref(false)

/**
 * 显示和隐藏抽屉
 * @param {Boolean} isShow 是否显示抽屉
 */
const changeShow = (isShow) => {
    show.value = isShow
}

// 用户表单值
const formValue = ref({
    nickname: '', // 昵称
})

// 用户表单验证规则
const formRules = {
    nickname: {
        required: true,
        message: '请输入昵称',
        trigger: 'input'
    }
}

// 表单组件实例
const formRef = ref(null)

// 获取用户基本信息
const getUserBasicInfo = async () => {
    noteServeRequest(userApi.getBasicInfo).then(response => {
        if (!response) return;
        setUserBasicInfo(response.data) // 设置用户的基本信息
    })
}

// 更新用户基本信息
const updateUserBasicInfo = async () => {
    // 手动验证表单
    await formRef.value?.validate(errors => {
        if (errors) throw "验证不成功";
    })

    // 请求 API
    let updateBasicInfoAPI = { ...userApi.updateBasicInfo }
    // 请求参数
    updateBasicInfoAPI.data = { nickname: formValue.value.nickname }
    // 发送请求
    noteServeRequest(updateBasicInfoAPI).then(response => {
        if (!response) return;
        setUserBasicInfo(response.data) // 设置用户的基本信息
    })
}

// 只要抽屉打开，就要发送获取用户基本信息请求
watch(
    () => show.value,
    newData => {
        if (newData) {
            formValue.value.nickname = nick_name.value; // 用户昵称初始化
            getUserBasicInfo();
        }
    }
)

// 更新按钮的显示
const showSubmitBtn = computed(() => {
    return nick_name.value !== formValue.value.nickname
})

// 图像裁剪对话框
const isShowModal = ref(false)

// 裁剪配置
const cropperOptions = {
    options: {
        viewMode: 1,
        dragMode: 'move',
        aspectRatio: 1,
        cropBoxResizable: false,
    },
    presetMode: {
        mode: 'fixedSize',
        width: 120,
        height: 120
    }
}

// 上传的输入框元素
const uploadInput = ref(null)

// 裁剪图像的的结果
const result = reactive({
    dataURL: '', // 裁剪后的 Base64 结果
    blobURL: '', // 裁剪后的 Blob 结果
})

// 图像裁剪地址
const pic = ref(null)

// 选择文件
function selectFile(e) {
    // 重置选择的结果
    pic.value = ''
    result.dataURL = ''
    result.blobURL = ''

    // 得到选则的文件（多个文件）
    const { files } = e.target
    if (!files || !files.length) return

    // 转换为 dataURL 并传递给 cropper 组件
    const file = files[0] // 第一个文件
    const reader = new FileReader()
    reader.readAsDataURL(file)
    reader.onload = () => {
        // 裁剪图像地址
        pic.value = String(reader.result)

        // 显示裁剪模态框
        isShowModal.value = true

        // 清除选件选择框值
        if (uploadInput.value) uploadInput.value.value = ''
    }
}

/**
 * 获取裁剪的结果
 */
async function getResult() {
    if (!cropper) return
    const base64 = cropper.getDataURL() // 获取裁剪后的 Base64 结果
    const blob = await cropper.getBlob() // 获取裁剪后的 Blob 结果
    if (!blob) return
    const file = await cropper.getFile() // 获取裁剪后的 File 结果

    console.log({ base64, blob, file })

    result.dataURL = base64 // 保存成数据源
    result.blobURL = URL.createObjectURL(blob) // 保存成数据源

    // 关闭裁剪模态框
    isShowModal.value = false

    // 上传用户的头像
    await uploadUserHeadPic(file)
}

/**
 * 上传用户的头像
 * @param {File} file 裁剪后的图片
 */
const uploadUserHeadPic = async (file) => {
    let formData = new FormData();
    formData.append('file', file);
    // 请求 API
    let updateHaedPicAPI = { ...userApi.updateHaedPic }
    // 请求参数
    updateHaedPicAPI.data = formData
    // 发送请求
    noteServeRequest(updateHaedPicAPI).then(response => {
        if (!response) return;
        setUserBasicInfo(response.data) // 设置用户的基本信息
    })
}

// 将数据源或者函数暴露出去
defineExpose({ changeShow })
</script>

<template>
    <!-- 用户基本信息（抽屉） -->
    <n-drawer v-model:show="show" :width="400">
        <n-drawer-content closable title="用户基本信息">
            <n-space justify="center">
                <!-- 头像 -->
                <label>
                    <n-avatar round :size="120" bordered :src="head_image" />
                    <!-- 文件选择框 -->
                    <input ref="uploadInput" type="file" accept="image/jpg, image/jpeg, image/png, image/gif"
                        @change="selectFile" style="display: none" />
                </label>
            </n-space>

            <n-form ref="formRef" :model="formValue" :rules="formRules" :show-require-mark="false" label-placement="left"
                label-width="auto" style="margin-top: 14px;">
                <n-form-item label=" 邮箱：">
                    <n-text style="margin-left: 12px;">{{ email }}</n-text>
                </n-form-item>
                <n-form-item label="昵称：" path="nickname">
                    <n-input v-model:value="formValue.nickname" maxlength="8"
                        style="--n-border: none; --n-color: transparent" />
                </n-form-item>
                <n-form-item label="等级：">
                    <n-tag style="margin-left: 12px;" type="success" :bordered="false">{{ level_info }}</n-tag>
                </n-form-item>
                <n-form-item label="注册时间：">
                    <n-text style="margin-left: 12px;" depth="3">{{ time }}</n-text>
                </n-form-item>
                <n-form-item :show-label="false" v-show="showSubmitBtn">
                    <n-button @click="updateUserBasicInfo" block secondary type="success">更新</n-button>
                </n-form-item>
            </n-form>
        </n-drawer-content>
    </n-drawer>


    <!-- 裁剪图像模态框 -->
    <n-modal title="头像上传" v-model:show="isShowModal" preset="card" style="width: 500px;height: 400px;"
        content-style="height: 0;padding: 0 24px">
        <!-- 裁剪图像组件 -->
        <VuePictureCropper v-bind="cropperOptions" :img="pic" style="height: 100%;" />
        <template #action>
            <n-space justify="end">
                <n-button>取消</n-button>
                <n-button @click="getResult">确定</n-button>
            </n-space>
        </template>
    </n-modal>
</template>